let isDone: boolean = false;
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];

let name3: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name3 }.

I'll be ${ age + 1 } years old next month.`;


// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [ 'hello',20]; // Error


enum Color {Red, Green, Blue}
let c: Color = Color.Green;

enum Color2 {Red = 1, Green = 2, Blue = 4}
let cc: Color2 = Color2.Green;


let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean


function warnUser(): void {
    console.log("This is my warning message");
}

// Not much else we can assign to these variables!
let u: undefined = undefined;
let n: null = null;



// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) {
    }
}


declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

//create(42); // Error
//create("string"); // Error
//create(false); // Error
//create(undefined); // Error

let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

let someValue2: any = "this is a string";

let strLength2: number = (someValue2 as string).length;




function foo() {
    // okay to capture 'a'
    return a;
}

// 不能在'a'被声明前调用'foo'
// 运行时应该抛出错误
foo();
let a;

function f(x) {
    var x;
    var x;

    if (true) {
        var x;
    }
}


let x3 = 10;
let x2 = 20; // 错误，不能在1个作用域里多次声明`x`
const numLivesForCat = 9;
//使用最小特权原则，所有变量除了你计划去修改的都应该使用const。 基本原则就是如果一个变量不需要对它写入，那么其它使用这些代码
//的人也不能够写入它们，并且要思考为什么会需要对这些变量重新赋值。 使用 const也可以让我们更容易的推测数据的流动。


let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2


function fa([first, second]: [number, number]) {
    console.log(first);
    console.log(second);
}
fa([1,2]);




let o = {
    aa: "foo",
    b: 12,
    c: "bar"
};
let { aa, b } = o;

({ aaa, b } = { aaa: "baz", b: 101 });

let { aaa, ...passthrough } = o;
let total = passthrough.b + passthrough.c.length;


function keepWholeObject(wholeObject: { a: string, b?: number }) {
    let { a, b = 1001 } = wholeObject;
}
function f({ a, b = 0 } = { a: "" }): void {
    // ...
}
f({ a: "yes" }); // ok, default b = 0
f(); // ok, default to {a: ""}, which then defaults b = 0
f({}); // error, 'a' is required if you supply an argument


let first1 = [1, 2];
let second1 = [3, 4];
let bothPlus = [0, ...first1, ...second1, 5];

let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };

let defaults2 = { food: "spicy", price: "$$", ambiance: "noisy" };
let search2= { food2: "rich", ...defaults };